package com.yumiusik.controller;

import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.ListUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.log4j.lf5.util.StreamUtils;
import org.json.JSONObject;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import pe.com.trestperu.common.listener.ContextLoaderListener;
import pe.com.trestperu.common.service.GenericService;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yumiusik.common.domain.AudioInformation;
import com.yumiusik.common.domain.PlayerDetailList;
import com.yumiusik.common.domain.PlayerList;
import com.yumiusik.common.domain.PlayerLogShare;
import com.yumiusik.common.domain.PlayerUser;
import com.yumiusik.util.YumiusikConstants;
import com.yumiusik.util.YumiusikUtils;

@SuppressWarnings("unchecked")
@Controller
public class YumiusikController {

	static final Log log = LogFactory.getLog(YumiusikController.class);

	public static String APP_SERVER_URL = StringUtils.EMPTY;

	private GenericService getGenericService(){
		return (GenericService)ContextLoaderListener.getBean(GenericService.class);
	}

	@RequestMapping(value = "/init")
	public String init(HttpServletRequest request, HttpServletResponse response) throws Exception {
		log.info("init :: inicio");
		log.info("RemoteHost :: " + request.getRemoteHost());
		log.info("User-Agent :: " + request.getHeader("User-Agent"));
		APP_SERVER_URL = YumiusikConstants.developer ? YumiusikConstants.LOCAL_APP_SERVER_URL : YumiusikConstants.APP_SERVER_URL;
		String shareID = StringUtils.EMPTY;
		String songID = request.getParameter("songID");
		String listID = StringUtils.EMPTY;
		try{
			listID = request.getParameter("listID");
			if(StringUtils.isNotEmpty(listID)) listID = URLDecoder.decode(listID, "UTF-8");
		}catch(Exception e){
			log.warn(e);
		}
		try{
			shareID = request.getParameter("shareID");
			if(StringUtils.isNotEmpty(shareID)) shareID = URLDecoder.decode(shareID, "UTF-8");
		}catch(Exception e){
			log.warn(e);
		}
		request.setAttribute("autoPlay", Boolean.FALSE);
		request.setAttribute("autoPlayList", Boolean.FALSE);
		if(StringUtils.isNotEmpty(shareID)){
			String shareKey = YumiusikUtils.decrypt(StringUtils.replace(shareID, " ", "+"));
			try{
				Long idShare = Long.parseLong(shareKey);
				PlayerLogShare playerLogShare = (PlayerLogShare)getGenericService().findById(PlayerLogShare.class, idShare);
				if(playerLogShare != null){
					playerLogShare.setListened(YumiusikConstants.SI_NO.SI);
					getGenericService().save(playerLogShare);
				}
			}catch(Exception e){
				log.error(e);
			}
		}
		if(StringUtils.isNotEmpty(songID)){
			AudioInformation audioInformation = (AudioInformation)getGenericService().findById(AudioInformation.class, songID);
			if(audioInformation != null){
				request.setAttribute("autoPlay", Boolean.TRUE);
				request.setAttribute("audioInformation", audioInformation);
			}
		}
		if(StringUtils.isNotEmpty(listID)){
			String listKey = YumiusikUtils.decrypt(StringUtils.replace(listID, " ", "+"));
			try{
				Long idList = Long.parseLong(listKey);
				PlayerList playerList = (PlayerList)getGenericService().findById(PlayerList.class, idList);
				if(playerList != null){
					request.setAttribute("autoPlayList", Boolean.TRUE);

					Map<String, Object> item = new HashMap<String, Object>();
					item.put("CODE", playerList.getCode());
					item.put("LIST_NAME", playerList.getListName());
					Map<String, Object> params = new HashMap<String, Object>();
					params.put("listCode", MapUtils.getLong(item, "CODE"));
					item.put("SONG_LIST", getGenericService().mapListar("youtubePlayer.getPlayerListDetail", params));
					request.setAttribute("playListAuto", item);
				}
			}catch(Exception e){
				log.error(e);
			}
		}
		request.setAttribute("APP_SERVER_URL", APP_SERVER_URL);
		log.info("init :: fin");
		return "init";
	}

	@RequestMapping(value = "/info")
	public @ResponseBody String info(@RequestParam("url") String urlYouTube, @RequestParam("tipo") String tipo, HttpServletRequest request, HttpServletResponse response) throws Exception {
		log.info("info :: inicio");
		// tipo ==>  Parametro que define si se regresa informacion de tipo ( high, mid, low )
		if(!urlYouTube.startsWith("http://")){
			urlYouTube = "http://" + urlYouTube;
		}
		log.info("urlYouTube :: " + urlYouTube);
		log.info("User-Agent :: " + request.getHeader("User-Agent"));
		String video_id = YumiusikUtils.getVideoIdFromURL(urlYouTube);
		AudioInformation audioInformation = (AudioInformation)getGenericService().findById(AudioInformation.class, video_id);

		Map<String, Object> information = new HashMap<String, Object>();

		if(audioInformation == null){
			URL url = new URL(YumiusikConstants.YOUTUBE_GET_DATA_URL + "/" + video_id);
			HttpURLConnection cnx = (HttpURLConnection) url.openConnection();
			cnx.setDoInput(true);
			cnx.setDoOutput(true);
			cnx.setRequestMethod("GET");
	
			// Leyendo la respuesta
			InputStream in = cnx.getInputStream();
			Document doc = YumiusikUtils.readXml(in);
			NodeList nodeList = doc.getElementsByTagName("media:content");
			Node node = nodeList.item(0);
	
			information.put("duration", node.getAttributes().getNamedItem("duration").getTextContent());
			nodeList = doc.getElementsByTagName("media:thumbnail");
			node = nodeList.item(0);
			information.put("image", node.getAttributes().getNamedItem("url").getTextContent());
	
			nodeList = doc.getElementsByTagName("media:title");
			node = nodeList.item(0);
			information.put("title", node.getTextContent());
	
			information.put("mp3", APP_SERVER_URL+ "mp3"+tipo+"/?url="+urlYouTube);
	
			in.close();

			audioInformation = (AudioInformation)ContextLoaderListener.getBean(AudioInformation.class);
			audioInformation.setVideo_id(video_id);
			audioInformation.setDuration(MapUtils.getLong(information, "duration"));
			audioInformation.setImage(MapUtils.getString(information, "image"));
			audioInformation.setTitle(MapUtils.getString(information, "title"));
			audioInformation.setLink(urlYouTube);
			audioInformation.setLength(new Long(-1));
			audioInformation.setValidate("NO");
			getGenericService().save(audioInformation);
		}else{
			information.put("id", audioInformation.getVideo_id());
			information.put("duration", audioInformation.getDuration());
			information.put("image", audioInformation.getImage());
			information.put("title", audioInformation.getTitle());
			information.put("length", audioInformation.getLength());
			information.put("link", audioInformation.getLink());
			information.put("mp3", APP_SERVER_URL+"mp3"+tipo+"/?url="+urlYouTube);
		}

		response.setContentType("text/xml");
		response.setCharacterEncoding("UTF-8");

		PrintWriter out = response.getWriter();
		out.print(YumiusikUtils.toXML(information, "information"));
		out.flush();
		out.close();

		log.info("info :: fin");
		return null;
	}

	/**
	 * Method to download and verify the file if exists
	 * 
	 * @param urlYouTube
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	@RequestMapping(value = "/verifyMP3")
	public void verifyMP3(@RequestParam("url") String urlYouTube, HttpServletRequest request, HttpServletResponse response) throws Exception {
		log.info("verifyMP3 :: inicio");
		if(!urlYouTube.startsWith("http://")){
			urlYouTube = "http://" + urlYouTube;
		}
		Map<String, Object> result = new HashMap<String, Object>();
		result.put("estado", "OK");
		result.put("responseText", "OK");
		String video_id = YumiusikUtils.getVideoIdFromURL(urlYouTube);
		String user_agent = request.getHeader("User-Agent");
		YumiusikUtils.saveLog(request, YumiusikConstants.TYPE_ACCESS.Verify, null, video_id);
		try{
			String status = YumiusikUtils.getStatusHolder(video_id);
			if(StringUtils.isEmpty(status)){
				String process = "verifyMP3";
				YumiusikUtils.registerStatusHolder(video_id, process, YumiusikUtils.STATUS_HOLDER.IN_PROCESS);
				YumiusikUtils.existsMP3(video_id, user_agent);
				YumiusikUtils.registerStatusHolder(video_id, process, YumiusikUtils.STATUS_HOLDER.ENDED);
			}else{
				result.put("estado", "WAIT");
				result.put("responseText", status);
			}
		}catch(Exception e){
			log.error(e);
			result.put("estado", "ERROR");
			result.put("responseText", e.getMessage());
			YumiusikUtils.sendEmail(video_id);
		}
		PrintWriter out = response.getWriter();	
		out.print("[["+(new ObjectMapper()).writeValueAsString(result)+"]]");
		out.flush();
		out.close();
		log.info("verifyMP3 :: fin");
	}

	/**
	 * Method to download file to browser
	 * 
	 * @param urlYouTube
	 * @param type
	 * @param request
	 * @param response
	 * @throws Exception
	 */
	public void writeMP3(String urlYouTube, String type, HttpServletRequest request, HttpServletResponse response) throws Exception {
		if(!urlYouTube.startsWith("http://")){
			urlYouTube = "http://" + urlYouTube;
		}
		String video_id = YumiusikUtils.getVideoIdFromURL(urlYouTube);
		YumiusikUtils.saveLog(request, YumiusikConstants.TYPE_ACCESS.Play, type, video_id);
		AudioInformation audioInformation = (AudioInformation)getGenericService().findById(AudioInformation.class, video_id);

		if(audioInformation == null){
			audioInformation = YumiusikUtils.createAudioInformation(video_id);
		}

		File mp3 = YumiusikUtils.returnMP3File(video_id, type, request.getHeader("User-Agent"));

		// Leyendo la respuesta
		FileInputStream fileInputStream = new FileInputStream(mp3);

		response.addHeader("Content-Type","application/octet-stream;");
		response.addHeader("Content-Length", String.valueOf(mp3.length()));
		response.addHeader("Accept-Ranges", "bytes");
		response.addHeader("Content-Disposition", "attachment; filename=\"" + audioInformation.getTitle() + ".mp3\"");

		BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
		
		long length = mp3.length();

		byte[] buffer = new byte[1024];
		int read = fileInputStream.read(buffer);
		while (read >= 0){
			if (read > 0){
				out.write(buffer, 0, read);
			}
			read = fileInputStream.read(buffer);
			length += buffer.length;
		}

		out.flush();
		out.close();
		fileInputStream.close();

		if(audioInformation.getLength().longValue() != length){
			audioInformation.setLength(new Long(length));
			getGenericService().save(audioInformation);
		}
	}

	@RequestMapping(value = "/mp3")
	public void mp3(@RequestParam("url") String urlYouTube, HttpServletRequest request, HttpServletResponse response) throws Exception {
		mp3high(urlYouTube, request, response);
	}

	@RequestMapping(value = "/mp3mobile")
	public void mp3mobile(@RequestParam("url") String urlYouTube, HttpServletRequest request, HttpServletResponse response) throws Exception {
		mp3low(urlYouTube, request, response);
	}

	@RequestMapping(value = "/mp3low")
	public void mp3low(@RequestParam("url") String urlYouTube, HttpServletRequest request, HttpServletResponse response) throws Exception {
		log.info("mp3low :: inicio");
		writeMP3(urlYouTube, "low", request, response);
		log.info("mp3low :: fin");
	}

	@RequestMapping(value = "/mp3mid")
	public void mp3mid(@RequestParam("url") String urlYouTube, HttpServletRequest request, HttpServletResponse response) throws Exception {
		log.info("mp3mid :: inicio");
		writeMP3(urlYouTube, "mid", request, response);
		log.info("mp3mid :: fin");
	}

	@RequestMapping(value = "/mp3high")
	public void mp3high(@RequestParam("url") String urlYouTube, HttpServletRequest request, HttpServletResponse response) throws Exception {
		log.info("mp3high :: inicio");
		writeMP3(urlYouTube, "high", request, response);
		log.info("mp3high :: fin");
	}

	@RequestMapping(value="/search")
	@ResponseBody
	public void search(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String urlYouTube = YumiusikConstants.YOUTUBE_GET_DATA_URL+"?"+request.getQueryString();
	
		YumiusikUtils.saveLog(request, YumiusikConstants.TYPE_ACCESS.Search, null, null);
		
		URL url = new URL(urlYouTube);	
		HttpURLConnection cnx = (HttpURLConnection) url.openConnection();
		cnx.setDoInput(true);
		cnx.setDoOutput(true);
		cnx.setRequestMethod("GET");

		InputStream in = cnx.getInputStream();
		String sb = new String(StreamUtils.getBytes(in), "UTF-8");
		String content_type = cnx.getContentType();
		in.close();
		cnx.disconnect();
		sb = StringUtils.replace(sb,"href='http://gdata.youtube.com/feeds/api/videos?","href='"+APP_SERVER_URL+"search/?");
		response.setContentType(content_type);
		response.setCharacterEncoding("UTF-8");
		PrintWriter out = response.getWriter();
		out.print(sb.toString());
		out.flush();
		out.close();
	}

	@RequestMapping(value="/related")
	@ResponseBody
	public void related(@RequestParam("url") String urlYouTube,@RequestParam("start-index") String start,@RequestParam("max-results") String max, HttpServletRequest request, HttpServletResponse response) throws Exception {
		String video_id = YumiusikUtils.getVideoIdFromURL(urlYouTube);
		String urlYouTubeSearch = MessageFormat.format(YumiusikConstants.YOUTUBE_GET_RELATED_URL, new Object[]{video_id,StringUtils.isEmpty(start) ? "1" : start ,StringUtils.isEmpty(max) ? "10" : max});
		YumiusikUtils.saveLog(request, YumiusikConstants.TYPE_ACCESS.Related, null, null);
		
		URL url = new URL(urlYouTubeSearch);	
		HttpURLConnection cnx = (HttpURLConnection) url.openConnection();
		cnx.setDoInput(true);
		cnx.setDoOutput(true);
		cnx.setRequestMethod("GET");

		InputStream in = cnx.getInputStream();
		String sb = new String(StreamUtils.getBytes(in), "UTF-8");
		in.close();
		cnx.disconnect();
		Map<String, Object> result = new HashMap<String, Object>();
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		DocumentBuilder builder = factory.newDocumentBuilder();
		Document doc = builder.parse(new InputSource(new StringReader(sb.toString())));
		NodeList linksNode = doc.getElementsByTagName("link");
		for(int i = 0; i < linksNode.getLength(); i++){
			Node node = linksNode.item(i);
			Node rel = node.getAttributes().getNamedItem("rel");
			Node href = node.getAttributes().getNamedItem("href");
			String text = rel.getTextContent();
			if("next".equals(text)){
				String next = href.getTextContent();
				url = new URL(next);
				result.put("next", StringUtils.replace(next,"https://gdata.youtube.com/feeds/api/videos/"+video_id+"/related?start-index="+(Integer.parseInt(StringUtils.isEmpty(max) ? "11" : "0") + Integer.parseInt(start) + Integer.parseInt(max))+"&max-results="+(StringUtils.isEmpty(max) ? "10" : max)+"&v=2",APP_SERVER_URL+"related/?url="+urlYouTube+"&start-index="+StringUtils.split(StringUtils.split(url.getQuery(),"&")[0], "=")[1]+"&max-results="+(StringUtils.isEmpty(max) ? "10" : max)));
			}
			if("previous".equals(text)){
				String previous = href.getTextContent();
				url = new URL(previous);
				int _start = Integer.parseInt(StringUtils.isEmpty(start) ? "1" : start);
				int _max = Integer.parseInt(StringUtils.isEmpty(max) ? "10" : max);
				int nstart = _start > _max ? _start - _max : _start;
				result.put("previous", StringUtils.replace(previous,"https://gdata.youtube.com/feeds/api/videos/"+video_id+"/related?start-index="+nstart+"&max-results="+_max+"&v=2",APP_SERVER_URL+"related/?url="+urlYouTube+"&start-index="+StringUtils.split(StringUtils.split(url.getQuery(),"&")[0], "=")[1]+"&max-results="+_max));
			}
		}
		if(MapUtils.getString(result, "next", null) == null){
			result.put("next", "");
		}
		if(MapUtils.getString(result, "previous", null) == null){
			result.put("previous", "");
		}
		List<Map<String, String>> entryResult = new ArrayList<Map<String, String>>();
		NodeList entriesNode = doc.getElementsByTagName("entry");
		for(int i = 0; i < entriesNode.getLength(); i++){
			Element element = (Element)entriesNode.item(i);
			Map<String, String> entry = new HashMap<String, String>();
			Element nodeID = (Element)element.getElementsByTagName("id").item(0);
			String txtid = nodeID.getTextContent();
			String[] splitid = StringUtils.split(txtid, ":");
			// Get ID
			entry.put("id", "http://gdata.youtube.com/feeds/api/videos/"+splitid[splitid.length - 1]);

			// Get title
			String textTitle = element.getElementsByTagName("media:title").item(0).getTextContent();
			entry.put("title", textTitle);

			// Get player
			String textPlayer = element.getElementsByTagName("media:player").item(0).getAttributes().getNamedItem("url").getTextContent();
			entry.put("vid", textPlayer);

			// Get imagen
			String textImagen = element.getElementsByTagName("media:thumbnail").item(0).getAttributes().getNamedItem("url").getTextContent();
			entry.put("img", textImagen);

			// Get segundos
			Element elementSegundos = (Element)element.getElementsByTagName("media:content").item(0);
			String textSegundos = elementSegundos.getAttribute("duration");
			entry.put("segundos", textSegundos);
			entryResult.add(entry);
		}
		result.put("entry", entryResult);
		JSONObject json = new JSONObject(result);
		response.setContentType("application/json");
		response.setCharacterEncoding("UTF-8");
		PrintWriter out = response.getWriter();
		out.print(json.toString());
		out.flush();
		out.close();
	}

	@RequestMapping(value = "/login")
	public ResponseEntity<Map<String, String>> login(HttpServletRequest request, HttpServletResponse response) throws Exception {
		log.info("login :: inicio");
		log.info("User-Agent :: " + request.getHeader("User-Agent"));
		String username = request.getParameter("user");
		String facebookID = request.getParameter("facebookID");
		String password = request.getParameter("pass");
		String type = request.getParameter("type");
		String codigo = request.getParameter("codigo");
		ObjectMapper mapper = new ObjectMapper();
		Map<String, String> result = new HashMap<String, String>();
		result.put("estado", "OK");
		Map<String, String> params = new HashMap<String, String>();
		params.put("type", type);
		params.put("email", username);
		params.put("facebookID", facebookID);
		params.put("codigo", codigo);

		List<Map<String, Object>> userList = (List<Map<String, Object>>)getGenericService().mapListar("youTubePlayer.getPlayerUser", params);
		if(CollectionUtils.isNotEmpty(userList)){
			Map<String, Object> user = userList.get(0);
			if(StringUtils.isNotEmpty(password)){
				if(!password.equals(MapUtils.getString(user, "PASS"))){
					result.put("estado", "ERROR");
					result.put("errorCode", "1");
					result.put("message", "User password error");
					return new ResponseEntity<Map<String, String>>(result, HttpStatus.BAD_REQUEST);
				}
			}
			user.remove("PASS");
			result.put("user", mapper.writeValueAsString(userList.get(0)));
		}else{
			result.put("estado", "ERROR");
			result.put("errorCode", "0");
			result.put("message", "Can't find user");
			return new ResponseEntity<Map<String, String>>(result, HttpStatus.BAD_REQUEST);
		}
		log.info("login :: fin");

		return new ResponseEntity<Map<String, String>>(result, HttpStatus.ACCEPTED);
	}

	@RequestMapping(value="/getAccountID")
	@ResponseBody
	public void getAccountID(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String username = request.getParameter("username");
		String password = request.getParameter("password");
		String facebookID = request.getParameter("facebookID");

		Map<String, String> params = new HashMap<String, String>();
		params.put("email", username);
		params.put("facebookID", null);
		params.put("codigo", null);
		params.put("type", null);

		List<Map<String, Object>> userList = (List<Map<String, Object>>)getGenericService().mapListar("youTubePlayer.getPlayerUser", params);

		response.setContentType("text/plain");
		response.setCharacterEncoding("UTF-8");
		PrintWriter out = response.getWriter();	
		if(CollectionUtils.isNotEmpty(userList)){
			Map<String, Object> item = userList.get(0);
			if(StringUtils.isNotEmpty(facebookID) && StringUtils.isEmpty(MapUtils.getString(item, "FACEBOOKID"))){
				PlayerUser user = (PlayerUser)getGenericService().findById(PlayerUser.class, MapUtils.getLong(item, "CODE"));
				user.setFacebookID(facebookID);
				getGenericService().save(user);
			}
			out.print(MapUtils.getLong(item, "CODE"));
		}else{
			PlayerUser user = new PlayerUser();
			user.setEmail(username);
			user.setPass(password);
			user.setUserType("F");
			getGenericService().save(user);
			out.print(String.valueOf(user.getCode()));
		}
		out.flush();
		out.close();
	}

	@RequestMapping(value="/getPlayListShared")
	@ResponseBody
	public void getPlayListShared(HttpServletRequest request, HttpServletResponse response) throws Exception {
		response.setContentType("text/plain");
		Map<String, Object> result = new HashMap<String, Object>();
		String userFrom = request.getParameter("userID");
		//String page = request.getParameter("page");  // numero de pagina
		String limit = request.getParameter("rows"); // Cantidad de registros por pagina
		//String sidx = request.getParameter("sidx"); // Columna para ordenar
		//String sord = request.getParameter("sord"); // Tipo orden ASC o DESC
		PrintWriter out = response.getWriter();
		Map<String, Object> params = new HashMap<String, Object>();
		if(StringUtils.isNotEmpty(userFrom) && !"undefined".equals(userFrom)){
			params.put("userFrom", userFrom);

			List<Map<String, Object>> _list = (List<Map<String, Object>>) getGenericService().mapListar("youtubePlayer.getCountShareList", params);
			if(CollectionUtils.isNotEmpty(_list)){
				Long _records = MapUtils.getLong((Map<String, Object>)_list.get(0), "TOTAL");
				Long _limit = Long.valueOf(limit);
				Long _total = Long.valueOf((long) Math.ceil(_records / (_limit > _records ? _records : _limit)));
				result.put("records", _records);
				result.put("total", _total);
				_list = (List<Map<String, Object>>) getGenericService().mapListar("youtubePlayer.getShareList", params);
				result.put("rows", _list);
			}else{
				result.put("records", 0);
				result.put("total", 0);
				result.put("rows", ListUtils.EMPTY_LIST);
			}
		}else{
			result.put("records", 0);
			result.put("total", 0);
			result.put("rows", ListUtils.EMPTY_LIST);
		}

		response.setCharacterEncoding("UTF-8");
		out.print((new ObjectMapper()).writeValueAsString(result));
		out.flush();
		out.close();
	}

	@RequestMapping(value="/dedicatedPlayList")
	@ResponseBody
	public void dedicatedPlayList(HttpServletRequest request, HttpServletResponse response) throws Exception {
		sharePlayList(request, response);
	}

	@RequestMapping(value="/sharePlayList")
	@ResponseBody
	public void sharePlayList(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String type = request.getParameter("by");
		String userFrom = request.getParameter("userFrom");
		String userTo = request.getParameter("userTo");
		String list_id = request.getParameter("listID");
		String message = request.getParameter("message");
		String subject = StringUtils.EMPTY;
		String shareID = StringUtils.EMPTY;
		String titleMessage = "<img src=\""+YumiusikController.APP_SERVER_URL+"/images/logo.png\" width=\"74\" height=\"74\" /><br /><br />";
		Map<String, String> result = new HashMap<String, String>();
		// Data to save in log
		Map<String, String> data = new HashMap<String, String>();
		data.put("mailFrom", userFrom);
		data.put("mailTo", userTo);
		data.put("playListID", list_id);
		data.put("message", message);
		if("email".equals(type)){
			YumiusikUtils.saveLog(request, YumiusikConstants.TYPE_ACCESS.ShareEmailSong, null, null);
			try{
				PlayerList playerList = (PlayerList)getGenericService().findById(PlayerList.class, new Long(list_id));
				String encryptListID = YumiusikUtils.encrypt(String.valueOf(playerList.getCode()));
				String encode = URLEncoder.encode(encryptListID, "UTF-8");
				PlayerLogShare playerLogShare = null;
				try{
					playerLogShare = YumiusikUtils.saveLogShare(request, data, YumiusikConstants.SI_NO.NO);
				}catch(Exception e){
					log.warn(e);
				}
				if(playerLogShare != null){
					shareID = URLEncoder.encode(YumiusikUtils.encrypt(String.valueOf(playerLogShare.getCode())), "UTF-8");
				}
				if(StringUtils.isNotEmpty(message)){
					subject = userFrom + " te dedica la cancion [" + playerList.getListName() + "]";
					message = titleMessage + message;
					message += "<br/>Haga click en el siguiente enlace para escucharla :: <a href=\""+YumiusikController.APP_SERVER_URL+"init?listID="+encode+"&shareID="+shareID+"\" target=\"_blank\">" + playerList.getListName() + "</a>";
				}else{
					subject = "YUMIUSIK SYSTEM - [" + playerList.getListName() + "]";
					message = titleMessage;
					message += "La siguiente cancion fue compartida para ti [" + playerList.getListName() + "]";
					message += "<br/>";
					message +="<br/>Haga click en el siguiente enlace para escucharla :: <a href=\""+YumiusikController.APP_SERVER_URL+"init?listID="+encode+"&shareID="+shareID+"\" target=\"_blank\">" + playerList.getListName() + "</a>";
				}
				YumiusikUtils.sendShareEmail(userFrom, userTo, subject, message);
				result.put("RESULT", "OK");
				if(playerLogShare != null){
					playerLogShare.setSended(YumiusikConstants.SI_NO.SI);
					getGenericService().save(playerLogShare);
				}
			}catch(Exception e){
				result.put("RESULT", "ERROR");
				result.put("MSG", e.getMessage());
				YumiusikUtils.saveLogShare(request, data, YumiusikConstants.SI_NO.NO);
			}
		}
		response.setContentType("text/plain");
		response.setCharacterEncoding("UTF-8");
		PrintWriter out = response.getWriter();	
		out.print((new ObjectMapper()).writeValueAsString(result));
		out.flush();
		out.close();
	}

	@RequestMapping(value="/shareSong")
	@ResponseBody
	public void dedicatedSong(HttpServletRequest request, HttpServletResponse response) throws Exception {
		shareSong(request, response);
	}

	@RequestMapping(value="/dedicatedSong")
	@ResponseBody
	public void shareSong(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String type = request.getParameter("by");
		String userFrom = request.getParameter("userFrom");
		String userTo = request.getParameter("userTo");
		String video_id = YumiusikUtils.getVideoIdFromURL(request.getParameter("songID"));
		String message = request.getParameter("message");
		String subject = StringUtils.EMPTY;
		String shareID = StringUtils.EMPTY;
		String titleMessage = "<img src=\""+YumiusikController.APP_SERVER_URL+"/images/logo.png\" width=\"74\" height=\"74\" /><br /><br />";
		Map<String, String> result = new HashMap<String, String>();
		// Data to save in log
		Map<String, String> data = new HashMap<String, String>();
		data.put("mailFrom", userFrom);
		data.put("mailTo", userTo);
		data.put("songID", video_id);
		data.put("message", message);
		if("email".equals(type)){
			YumiusikUtils.saveLog(request, YumiusikConstants.TYPE_ACCESS.ShareEmailSong, null, null);
			try{
				AudioInformation audioInformation = (AudioInformation)getGenericService().findById(AudioInformation.class, video_id);
				PlayerLogShare playerLogShare = null;
				try{
					playerLogShare = YumiusikUtils.saveLogShare(request, data, YumiusikConstants.SI_NO.NO);
				}catch(Exception e){
					log.warn(e);
				}
				if(playerLogShare != null){
					shareID = URLEncoder.encode(YumiusikUtils.encrypt(String.valueOf(playerLogShare.getCode())), "UTF-8");
				}
				String image = "<img src=\""+audioInformation.getImage()+"\" width=\"120\" height=\"100\" alt=\""+audioInformation.getTitle()+"\"/>";
				if(StringUtils.isNotEmpty(message)){
					subject = userFrom + " te dedica la cancion [" + audioInformation.getTitle() + "]";
					message = titleMessage + message;
					message += "<br/>";
					message += image;
					message += "<br/>Haga click en el siguiente enlace para escucharla :: <a href=\""+YumiusikController.APP_SERVER_URL+"init?songID="+video_id+"&shareID="+shareID+"\" target=\"_blank\">" + audioInformation.getTitle() + "</a>";
				}else{
					subject = "YUMIUSIK SYSTEM - [" + audioInformation.getTitle() + "]";
					message = titleMessage;
					message += "La siguiente cancion fue compartida para ti [" + audioInformation.getTitle() + "]";
					message += "<br/>";
					message += image;
					message +="<br/>Haga click en el siguiente enlace para escucharla :: <a href=\""+YumiusikController.APP_SERVER_URL+"init?songID="+video_id+"&shareID="+shareID+"\" target=\"_blank\">" + audioInformation.getTitle() + "</a>";
				}
				YumiusikUtils.sendShareEmail(userFrom, userTo, subject, message);
				result.put("RESULT", "OK");
				if(playerLogShare != null){
					playerLogShare.setSended(YumiusikConstants.SI_NO.SI);
					getGenericService().save(playerLogShare);
				}
			}catch(Exception e){
				result.put("RESULT", "ERROR");
				result.put("MSG", e.getMessage());
				YumiusikUtils.saveLogShare(request, data, YumiusikConstants.SI_NO.NO);
			}
		}
		response.setContentType("text/plain");
		response.setCharacterEncoding("UTF-8");
		PrintWriter out = response.getWriter();	
		out.print((new ObjectMapper()).writeValueAsString(result));
		out.flush();
		out.close();
	}

	@RequestMapping(value="/saveAllPlayList")
	@ResponseBody
	public void saveAllPlayList(HttpServletRequest request, HttpServletResponse response) throws Exception {
		log.info("saveAllPlayList :: inicio");
		String json = request.getParameter("info");
		Long playerUser = new Long(request.getParameter("userID"));
		PlayerList playList = new PlayerList();

		JsonFactory factory = new JsonFactory();
		ObjectMapper mapper = new ObjectMapper(factory);
		TypeReference<List<HashMap<String,Object>>> valueTypeRef = new TypeReference<List<HashMap<String,Object>>>() {};
		List<HashMap<String,Object>> info = mapper.readValue(json, valueTypeRef);
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		Map<String, Object> result_data = new HashMap<String, Object>();
		for(int i = 0; i < info.size(); i++){
			HashMap<String,Object> item = info.get(i);
			Long codigo = MapUtils.getLong(item, "code");
			String listName = MapUtils.getString(item, "name");
			List<HashMap<String,String>> songList = (List<HashMap<String,String>>)MapUtils.getObject(item, "songList");
			if(codigo == -1){
				playList.setActive("SI");
				playList.setListName(listName);
				playList.setPlayerUser(playerUser);
				getGenericService().save(playList);
			}else{
				playList = (PlayerList)getGenericService().findById(PlayerList.class, codigo);
			}
			result_data.put("playList", playList.getCode());
			if(CollectionUtils.isNotEmpty(songList)){
				List<Object> resultList = new ArrayList<Object>();
				for(int j = 0; j < songList.size(); j++){
					HashMap<String,String> song = songList.get(j);
					PlayerDetailList detail = new PlayerDetailList();
					detail.setCode(MapUtils.getLong(song, "code") == -1 ? null : MapUtils.getLong(song, "code"));
					detail.setListCode(playList.getCode());
					detail.setPlayOrder(MapUtils.getLong(song, "order"));
					detail.setSongID(YumiusikUtils.getVideoIdFromURL(MapUtils.getString(song, "link")));
					getGenericService().save(detail);
					resultList.add(detail.getCode());
				}
				result_data.put("songList", resultList);
			}
			result.add(result_data);
		}

		PrintWriter out = response.getWriter();
		out.print((new ObjectMapper()).writeValueAsString(result));
		out.flush();
		out.close();
		log.info("saveAllPlayList :: fin");
	}

	@RequestMapping(value="/savePlayList")
	@ResponseBody
	public void savePlayList(HttpServletRequest request, HttpServletResponse response) throws Exception {
		log.info("savePlayList :: inicio");
		String xml = request.getParameter("xml");
		String json = request.getParameter("info");
		Long playerUser = new Long(request.getParameter("userID"));
		PlayerList playList = new PlayerList();
		Map<String, Object> result = new HashMap<String, Object>();
		if(StringUtils.isNotEmpty(json)){
			JsonFactory factory = new JsonFactory();
			ObjectMapper mapper = new ObjectMapper(factory);
			TypeReference<HashMap<String,Object>> valueTypeRef = new TypeReference<HashMap<String,Object>>() {};
			HashMap<String,Object> item = mapper.readValue(json, valueTypeRef);
			Long codigo = MapUtils.getLong(item, "code");
			String listName = MapUtils.getString(item, "name");
			List<HashMap<String, String>> songList = (List<HashMap<String, String>>)MapUtils.getObject(item, "songList");
			if(codigo == -1){
				playList.setActive("SI");
				playList.setListName(listName);
				playList.setPlayerUser(playerUser);
				getGenericService().save(playList);
			}else{
				playList = (PlayerList)getGenericService().findById(PlayerList.class, codigo);
			}
			result.put("playList", playList.getCode());
			if(CollectionUtils.isNotEmpty(songList)){
				List<Object> resultList = new ArrayList<Object>();
				for(int j = 0; j < songList.size(); j++){
					HashMap<String, String> song = songList.get(j);
					PlayerDetailList detail = new PlayerDetailList();
					detail.setCode(MapUtils.getLong(song, "code") == -1 ? null : MapUtils.getLong(song, "code"));
					detail.setListCode(playList.getCode());
					detail.setPlayOrder(MapUtils.getLong(song, "order"));
					detail.setSongID(YumiusikUtils.getVideoIdFromURL(MapUtils.getString(song, "link")));
					getGenericService().save(detail);
					resultList.add(detail.getCode());
				}
				result.put("songList", resultList);
			}
		}else{
			String playListName = request.getParameter("name");
			Long playListID = new Long(request.getParameter("code"));
			if(playListID.longValue() == -1){
				playList.setActive("SI");
				playList.setListName(playListName);
				playList.setPlayerUser(playerUser);
				getGenericService().save(playList);
			}else{
				playList = (PlayerList)getGenericService().findById(PlayerList.class, playListID);
			}
			result.put("playList", playList.getCode());
			Map<String, Long> params = new HashMap<String, Long>();
			params.put("listCode", playListID);
			getGenericService().executeVoidProcedure("youtubePlayer.deletePlayerListDetail", params);
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			try{
				DocumentBuilder builder = factory.newDocumentBuilder();
				Document dom = builder.parse(new ByteArrayInputStream(xml.getBytes()));
				Element root = dom.getDocumentElement();
				NodeList items = root.getChildNodes();
				List<Object> resultList = new ArrayList<Object>();
				for (int i = 0; i < items.getLength(); i++){
					HashMap<String, Object> data = new HashMap<String, Object>();
					Node item = items.item(i);
					NodeList information = item.getChildNodes();
					for(int j = 0; j < information.getLength(); j++){
						Node nodo = information.item(j);
						data.put(nodo.getNodeName(), nodo.getTextContent());
					}
					PlayerDetailList detail = new PlayerDetailList();
					detail.setListCode(playList.getCode());
					detail.setPlayOrder(new Long(i));
					detail.setSongID(YumiusikUtils.getVideoIdFromURL(MapUtils.getString(data, "songYT") != null ? MapUtils.getString(data, "songYT") : MapUtils.getString(data, "#cdata-section")));
					getGenericService().save(detail);
					resultList.add(detail.getCode());
				}
				result.put("songList", resultList);
			}catch(Exception e){
				log.error(e);
			}
		}

		PrintWriter out = response.getWriter();
		out.print((new ObjectMapper()).writeValueAsString(result));
		out.flush();
		out.close();
		log.info("savePlayList :: fin");
	}

	@RequestMapping(value="/deleteSong")
	@ResponseBody
	public void deleteSong(HttpServletRequest request, HttpServletResponse response) throws Exception {
		log.info("deleteSong :: inicio");
		Map<String, String> result = new HashMap<String, String>();
		result.put("RESULT", "OK");
		String songID = request.getParameter("songID");

		try{
			PlayerDetailList playerDetailList = (PlayerDetailList)getGenericService().findById(PlayerDetailList.class, Long.valueOf(songID));
			if(playerDetailList != null){
				getGenericService().deleteById(PlayerDetailList.class, playerDetailList.getCode());
			}
		}catch(Exception e){
			result.put("RESULT", "ERROR");
			result.put("MSG", e.getMessage());
		}

		PrintWriter out = response.getWriter();
		out.print((new ObjectMapper()).writeValueAsString(result));
		out.flush();
		out.close();
		log.info("deleteSong :: fin");
	}

	@RequestMapping(value = "/returnListFromID")
	public void returnListFromID(@RequestParam("playlistID") String playlistID, HttpServletRequest request, HttpServletResponse response) throws Exception {
		log.info("returnListFromID :: inicio");
		Map<String, Object> result = new HashMap<String, Object>();
		result.put("estado", "OK");
		result.put("responseText", "OK");
		try{
			PlayerList playerList = (PlayerList)getGenericService().findById(PlayerList.class, new Long(playlistID));
			Map<String, Object> params = new HashMap<String, Object>();
			params.put("listCode", playerList.getCode());
			List<Map<String, String>> list = (List<Map<String, String>>) getGenericService().mapListar("youtubePlayer.getPlayerListDetail", params);
			result.put("list", (new ObjectMapper()).writeValueAsString(list));
		}catch(Exception e){
			result.put("estado", "ERROR");
			result.put("responseText", e.getMessage());
		}
		PrintWriter out = response.getWriter();	
		out.print((new ObjectMapper()).writeValueAsString(result));
		out.flush();
		out.close();
		log.info("returnListFromID :: fin");
	}

	@RequestMapping(value = "/returnSongFromID")
	public void returnSongFromID(@RequestParam("songID") String songID, HttpServletRequest request, HttpServletResponse response) throws Exception {
		log.info("returnSongFromID :: inicio");
		Map<String, Object> result = new HashMap<String, Object>();
		result.put("estado", "OK");
		result.put("responseText", "OK");
		try{
			AudioInformation audioInformation = (AudioInformation)getGenericService().findById(AudioInformation.class, songID);
			Map<String, Object> song = new HashMap<String, Object>();
			song.put("codigo", audioInformation.getVideo_id());
			song.put("link", audioInformation.getLink());
			song.put("title", audioInformation.getTitle());
			song.put("image_link", audioInformation.getImage());
			song.put("segundos", audioInformation.getDuration());
			//audioInformation
			result.put("result", song);
		}catch(Exception e){
			result.put("estado", "ERROR");
			result.put("responseText", e.getMessage());
		}
		PrintWriter out = response.getWriter();	
		out.print((new ObjectMapper()).writeValueAsString(result));
		out.flush();
		out.close();
		log.info("returnSongFromID :: fin");
	}

	@RequestMapping(value = "/getListDetail")
	public void getListDetail(@RequestParam("playlistID") String playlistID, HttpServletRequest request, HttpServletResponse response) throws Exception {
		log.info("getListDetail :: inicio");
		try{
			Map<String, Object> params = new HashMap<String, Object>();
			params.put("listCode", playlistID);
			List<Map<String, String>> list = (List<Map<String, String>>) getGenericService().mapListar("youtubePlayer.getPlayerListDetail", params);
			response.setContentType("text/plain");
			PrintWriter out = response.getWriter();	
			out.print(YumiusikUtils.convertToString(list));
			out.flush();
			out.close();
		}catch(Exception e){
			e.printStackTrace();
		}
		log.info("getListDetail :: fin");
	}

	@RequestMapping(value = "/countPlayListFromUser")
	public void countPlayListFromUser(@RequestParam("userID") String userID, HttpServletRequest request, HttpServletResponse response) throws Exception {
		log.info("getPlayListFromUser :: inicio");
		try{
			Map<String, Object> params = new HashMap<String, Object>();
			params.put("user", userID);
			List<Map<String, String>> list = (List<Map<String, String>>) getGenericService().mapListar("youtubePlayer.getPlayerList", params);			
			response.setContentType("text/plain");
			PrintWriter out = response.getWriter();
			out.print(String.valueOf((CollectionUtils.isNotEmpty(list) ? (list.size() - 1) : 0)));
			out.flush();
			out.close();
		}catch(Exception e){
			e.printStackTrace();
		}
		log.info("getPlayListFromUser :: fin");
	}

	@RequestMapping(value = "/getPlayListFromUser")
	public void getPlayListFromUser(@RequestParam("userID") String userID, HttpServletRequest request, HttpServletResponse response) throws Exception {
		log.info("getPlayListFromUser :: inicio");
		try{
			Map<String, Object> params = new HashMap<String, Object>();
			params.put("user", userID);
			List<Map<String, Object>> list = (List<Map<String, Object>>) getGenericService().mapListar("youtubePlayer.getPlayerList", params);
			for(int i = 0; i < list.size(); i++){
				Map<String, Object> item = list.get(i);
				params = new HashMap<String, Object>();
				params.put("listCode", MapUtils.getLong(item, "CODE"));
				item.put("SONG_LIST", getGenericService().mapListar("youtubePlayer.getPlayerListDetail", params));
				list.set(i, item);
			}
			response.setContentType("text/plain");
			PrintWriter out = response.getWriter();
			out.print((new ObjectMapper()).writeValueAsString(list));
			out.flush();
			out.close();
		}catch(Exception e){
			e.printStackTrace();
		}
		log.info("getPlayListFromUser :: fin");
	}

}